// Learn TypeScript:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html
import axios from 'axios'

const { ccclass, property } = cc._decorator;

@ccclass
class Base extends cc.Component {

    _template: {} = null
    _model: string = null

    @property()
    blockWidth: number = 68

    @property()
    blockHeight: number = 68

    @property({
        tooltip: '最大横边'
    })
    rowMax: number = 9

    @property({
        tooltip: '最大竖边'
    })
    colMax: number = 9

    @property({
        tooltip: '最大斜边'
    })
    bevelEdgeMax: number = 9

    @property({
        tooltip: '最小链接值'
    })
    connectMin: number = 3
    totalInit = 0
    maxStepNumber = 0 //最大能走步数
    remainingSteps = 0
    data = null
    Node
    Mask

    set step(value) {
        this.remainingSteps = value
        this.setScore('setStepNumber', value)
    }
    get step() {
        return this.remainingSteps
    }

    get total() {
        return this.totalInit
    }

    set total(value) {
        this.totalInit = value
        this.setScore('setScore', value)
    }



    async getTemplate() {
        // return await axios.get('../Data/template.json')
        if (this.data) return this.data
        if (this._template && this._model) {
            return {
                template: this._template,
                model: this._model
            }
        }
        const data = require('../Data/template.json')
        this.maxStepNumber = data.maxStepNumber
        this.step = data.maxStepNumber
        cc.systemEvent.emit('setTarget', data.target, this)
        this.data = data
        return data
    }

    getSibling(direction, id) {
        const equation = {
            'left': -10,
            'right': 10,
            'bottom': -1,
            'top': 1,
            'upperRight': -11,
            'lowerRight': 9,
            'upperLeft': -9,
            'lowerLeft': -11,
        }
        return this._template[id + equation[direction]]
    }

    exchange(id, nextId) { // 格子互换

        const item = { ...this._template[id] }
        const nextItem = { ...this._template[nextId] }
        if (!this._template[id] || !this._template[nextId]) return

        this._template[id].info = nextItem.info
        this._template[nextId].info = item.info
    }

    setTemplateItem(id, info) {
        this._template[id].info = info
    }

    async getPos(callback: Function) { // 获取当前棋子位置
        const {
            template,
            model
        }: {
            template: [],
            model: string
        } = await this.getTemplate()
        this._template = {}
        this._model = model
        template.forEach((item: {
            position: [
                number,
                number
            ],
            without?: boolean
            monsterInitType?: string
        }, index) => {
            const {
                position,
                without
            } = item
            if (without) return item
            let {
                x, y
            } = this.createdfixedPoint(position)
            const id = Number(`${item.position[0]}${item.position[1]}`)
            const data = {
                ...item,
                id,
                index,
                x, y
            }
            this._template[id] = {
                ...data,
                ...callback(data)
            }
        })
    }

    randomNum = (max: number, min: number) => Math.floor(Math.random() * (max - min + 1) + min)

    excludedRandomNumber(max: number, min: number, never?: number[]) { // 得到一个区间永远不会出现数
        if (!never) return this.randomNum(max, min)
        let num = null
        do {
            num = this.randomNum(max, min)
        }
        while (never.indexOf(num) !== -1) {
            return num
        }
    }

    createdfixedPoint(list: [
        number,
        number
    ]) { // 定点模式
        return {
            x: list[0] * this.blockWidth,
            y: list[1] * this.blockHeight
        }
    }

    initPool({ // 初始化对象池
        initCount = 1,
        name,
        prefab
    }): object {
        if (this[`${name}Pool`]) return
        if (prefab) this[`${name}Prefab`] = prefab
        this[`${name}Pool`] = new cc.NodePool();
        for (let i = 0; i < initCount; ++i) {
            let node = cc.instantiate(this[`${name}Prefab`]); // 创建节点
            this[`${name}Pool`].put(node); // 通过 put 接口放入对象池
        }
        return this
    }

    recyclePool({ name, node }) {
        this[`${name}Pool`].put(node)
        return this
    }

    createNode({
        name
    }) {
        let node: cc.Node = null;
        let pool = this[`${name}Pool`]
        let prefab = this[`${name}Prefab`]
        if (pool.size() > 0) { // 通过 size 接口判断对象池中是否有空闲的对象
            node = pool.get();
        } else { // 如果没有空闲对象，也就是对象池中备用对象不够时，我们就用 cc.instantiate 重新创建
            node = cc.instantiate(prefab);
        }
        return node
    }

    checkSame() { // 检测是否有相同棋子
        const same = []
        let length = 0
        const fn = (item) => {
            if (!item.info) return
            const {
                id
            } = item
            const {
                uuid,
                monsterType
            } = item.info
            const getSameId = ({
                id, value, sameArray, key, first
            }: {
                id: number,
                value: number,
                sameArray: number[],
                key: string,
                first?: boolean
            }) => { // 获取相同id
                /**
                 * 以最小连接值为判断依据 如果小于最小连接就不算入数组中
                 * 把数组切分为多个链接成功数组
                 */
                let findItme = { ...this._template[id + value] }
                let curentItem = { ...this._template[id] }
                if (first && curentItem[`${key}isUser`]) return []  // 当前是第一次查找 并且当前已经被查出过
                if (
                    !findItme // 没有查找到下一个
                    || !findItme.info // 没有查找到下一个节点
                    || !uuid // 没有当前节点
                    || monsterType != findItme.info.monsterType // 当前和下一个名称不同
                ) return sameArray.length >= this.connectMin ? sameArray : []
                if (first) sameArray.push(id) // 首次加入
                sameArray.push(findItme.id)
                findItme[`${key}isUser`] = true
                return getSameId({
                    id: id + value, value, sameArray, key
                })
            }
            let row = getSameId({
                id, value: 10, sameArray: [], key: 'row', first: true
            })
            let col = getSameId({
                id, value: 1, sameArray: [], key: 'col', first: true
            })
            let bevel = getSameId({
                id, value: 11, sameArray: [], key: 'bevel', first: true
            })
            let bevel2 = getSameId({
                id, value: -9, sameArray: [], key: 'bevel2', first: true
            })

            if (row.length) same.push(row)
            if (col.length) same.push(col)
            if (bevel.length) same.push(bevel)
            if (bevel2.length) same.push(bevel2)
            length += row.length + col.length + bevel.length + bevel2.length
        }
        for (let i in this._template) {
            fn({ ...this._template[i] })
        }
        return {
            same,
            length
        }
    }

    getGroup() { // 获取分组
        let _template = []
        for (let i in this._template) {
            _template[i] = this._template[i]
        }
        let dg = []
        let group = []
        let lastId = -1
        _template.forEach((item, index) => {
            const id = item.id
            if (lastId === -1 || id === lastId + 1) {
                group.push(item)
                if (index === _template.length - 1) dg.push(group)
            } else {
                dg.push(group)
                group = [item]
                lastId = -1
            }
            lastId = id
        })
        return {
            group: dg,
            length: _template.length,
            _template
        }
    }

    setScore(event: string, num: number) {
        cc.systemEvent.emit(event, num)
    }
}

window.$base = new Base()
